//
//  UINavigationController+BGTransition.m
//  Nav
//
//  Created by Lam BG on 2018/8/8.
//  Copyright © 2018年 YZ. All rights reserved.
//

#import "UINavigationController+BGTransition.h"
#import "UIViewController+BGTransition.h"

#include <objc/runtime.h>

@interface UINavigationController ()

@end

@implementation UINavigationController (BGTransition)

+ (void)load {

    // 交换弹出时的方法，作为拦截判断
    SEL popOriginalSEL = @selector(popViewControllerAnimated:);
    SEL popRelpaceSEL  = @selector(bg_popViewControllerAnimated:);
    [self switchFunctionWithOriginal:popOriginalSEL andReplace:popRelpaceSEL];
    
    // 交换手势滑动，可以获得滑动完成的百分比
    SEL updateOriginalSEL = NSSelectorFromString(@"_updateInteractiveTransition:");
    SEL updateReplaceSEL  = @selector(bg_updateInteractiveTransition:);
    [self switchFunctionWithOriginal:updateOriginalSEL andReplace:updateReplaceSEL];
}

- (void)bg_updateNavAlpha:(CGFloat)alpha {
    
    // 获取导航栏视图
    UIView *navBackgroundView = [[self.navigationBar subviews] objectAtIndex:0];
    // 设置导航栏背景透明度
    navBackgroundView.alpha = alpha;
    
    // effect view
    Ivar backgroundOpacityVar = class_getInstanceVariable([UINavigationBar class], "__backgroundOpacity");
    if(backgroundOpacityVar){
        
        // 遮罩设置透明度
        [self.navigationBar setValue:@(alpha) forKey:@"__backgroundOpacity"];
    }
}

#pragma mark - 按钮返回 / 右滑返回

- (UIViewController *)bg_popViewControllerAnimated:(BOOL)animated {
    
    // 先弹出
    UIViewController *popVC = [self bg_popViewControllerAnimated:animated];
    // 获取最顶 vc
    UIViewController *topVC = [self topViewController];
    
    // 查找右滑返回事件
    for (UIGestureRecognizer *popGesture in self.interactivePopGestureRecognizer.view.gestureRecognizers) {
        if ([popGesture isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) {
            
            UIScreenEdgePanGestureRecognizer *edgePan = (UIScreenEdgePanGestureRecognizer*)popGesture;
            if (UIGestureRecognizerStatePossible == edgePan.state) {
                
                // 触发的是按钮返回
                self.bg_isEdgePan = NO;
                [topVC resetTransitionStyle];
                
            } else if (UIGestureRecognizerStateBegan == edgePan.state) {
                
                // 右滑返回
                self.bg_isEdgePan = YES;
                topVC.bg_navTitleColor = topVC.bg_navTitleColor;
                
                // 关心返回时成功和失败的回调
                id<UIViewControllerTransitionCoordinator> coordinator = topVC.transitionCoordinator;
                // 监听手势返回的交互改变
                if (coordinator != nil) {
                    if (@available(iOS 10.0, *)) {
                        
                        [coordinator notifyWhenInteractionChangesUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context){
                            
                            // 处理回调
                            [self handleNotifyBlock:context];
                        }];
                    } else {
                        
                        [coordinator notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
                            
                            // 处理回调
                            [self handleNotifyBlock:context];
                        }];
                    }
                }
            }
        }
    }
    
    return popVC;
}

// 处理手势滑动过程当中松手回调
- (void)handleNotifyBlock:(id<UIViewControllerTransitionCoordinatorContext> _Nonnull)context {
    
    if ([context isCancelled]) {
        
        // 取消 返回当前页
        CGFloat duration  = [context transitionDuration] * [context percentComplete];
        UIViewController *formVC = [context viewControllerForKey:UITransitionContextFromViewControllerKey];
        CGFloat fromAlpha = formVC.bg_navAlpha;
        
        // 渐变
        [UIView animateWithDuration:duration animations:^{

            [formVC resetTransitionStyle];
            [self bg_updateNavAlpha:fromAlpha];
        }];
        
    } else {
        
        // 成功 返回上一页
        CGFloat duration = [context transitionDuration] * (1 - [context percentComplete]);
        UIViewController *toVC = [context viewControllerForKey:UITransitionContextToViewControllerKey];
        CGFloat toAlpha = toVC.bg_navAlpha;
        
        // 渐变
        [UIView animateWithDuration:duration animations:^{

            [toVC resetTransitionStyle];
            [self bg_updateNavAlpha:toAlpha];
        }];
    }
}

#pragma mark - 滑动更新

// 滑动过程中只关心透明度即可
- (void)bg_updateInteractiveTransition:(CGFloat)percent {
    
    [self bg_updateInteractiveTransition:percent];
    UIViewController *topVC = self.topViewController;
    if(topVC){
        // 转场的上下文信息
        id <UIViewControllerTransitionCoordinator> coordinator = topVC.transitionCoordinator;
        if(coordinator != nil){
            
            CGFloat fromAlpha  = [coordinator viewControllerForKey:UITransitionContextFromViewControllerKey].bg_navAlpha;
            CGFloat toAlpha    = [coordinator viewControllerForKey:UITransitionContextToViewControllerKey].bg_navAlpha;
            CGFloat newAlpha     = fromAlpha + ((toAlpha - fromAlpha ) * percent);
            // 滑动时修改透明度
            [self bg_updateNavAlpha:newAlpha];
        }
    }
}

#pragma mark - switch function

+ (void)switchFunctionWithOriginal:(SEL)originalSEL andReplace:(SEL)replaceSEL {
    
    // 替换方法
    Method originalMethod = class_getInstanceMethod(self, originalSEL);
    Method replaceMethod  = class_getInstanceMethod(self, replaceSEL);
    
    method_exchangeImplementations(originalMethod, replaceMethod);
}

#pragma mark - Getter / Setter

- (BOOL)isBg_isEdgePan {
    
    return [objc_getAssociatedObject(self, _cmd) boolValue];
}

- (void)setBg_isEdgePan:(BOOL)bg_isEdgePan {
    
    objc_setAssociatedObject(self, @selector(isBg_isEdgePan), @(bg_isEdgePan), OBJC_ASSOCIATION_COPY_NONATOMIC);
}

@end
















